home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-01
/
trunk.zip
/
TRUNK.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-01-04
|
10KB
|
307 lines
/* QuickC source for TRUNK */
/***************************************************************************/
/***************************************************************************/
/**
*** TRUNK -- a replacement for the MS-DOS 'TREE' command. TREE allows only
*** one option ('/F'--similar to the one implemented in TRUNK), but more
*** to the point, the output is verbose and completely unsuited for passing
*** to other programs. TRUNK is fully redirectable using MS-DOS redirection
*** and pipes.
***
*** Command line option flags are evaluated in left-to-right order.
*** Flags may conflict with each other, and the flag to the right takes
*** precedence--e.g. the command line 'TRUNK /F /o' will print only a
*** summary, no file names.
***
*** Enjoy.
***
*** Official TRUNK soundtrack:
*** "Fleetwood Mac in Chicago" Sire: SASH 3175-2 (C) 1975, or
*** Blue Horizon: BH 3801 (C) 1969
**/
/***************************************************************************/
/***************************************************************************/
#include <stdio.h>
#include <dos.h>
#include <sys\types.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <direct.h>
int puti(int, char *, char *);
char *namecat(unsigned char *, unsigned char *);
int delve(unsigned char *);
typedef unsigned char path[68];
char version[]="\nTRUNK v0.96, 18 Feb 1988, by Mike O'Regan";
int dirs_found=0;
int files_found=0;
unsigned int srch_attrib=_A_NORMAL | _A_RDONLY | _A_SUBDIR;
int summary=0;
int print_dirs=1;
int print_files=0;
int force_lower=0;
int help=0;
int info=0;
extern int errno;
extern char *sys_errlist[];
/***************************************************************************/
/***************************************************************************/
/**
*** main
**/
/***************************************************************************/
/***************************************************************************/
void main(int argc, char *argv[])
{
path current_dir;
unsigned char *cwd_ptr=current_dir;
path search_dir;
unsigned char *search_ptr=search_dir;
int n;
/**
*** Get the current working directory for later. If there is an error,
*** cwd_ptr will equal NULL. An error should only be caused by an
*** illegally long path name.
**/
cwd_ptr=getcwd(current_dir, sizeof(path));
if (cwd_ptr == NULL) {
puts(sys_errlist[errno]);
return;
}
/**
*** Process any command line arguments that are flags. The last argument
*** is assumed to be the pathname. Since the pathname is not required, the
*** last argument may be a flag as well.
**/
if (argc > 1) {
for (n=1; n < argc; n++) /* argv[0] always == TRUNK */
{
if (argv[n][0] == '/')
switch (argv[n][1]) {
case 'y': srch_attrib |= _A_SYSTEM;
case 'h': srch_attrib |= _A_HIDDEN;
break;
case 'o': print_dirs=0;
print_files=0;
case 's': summary=1;
break;
case 'F': print_dirs=0;
print_files=1;
break;
case 'l': force_lower=1; break;
case 'v': puts(version);
return;
case '?': help=1; break;
case '$': info=1; break;
}
} /* for (n=1; n < argc-1; n++) */
/**
*** If help was requested (through the -? flag or by TRUNK HELP), print
*** a help message and quit.
**/
if ( (help) || (argv[1][0] == '?') ) {
puts("\nTRUNK [?] [/?] [/h] [/y] [/F] [/s] [/o] [/l] [/v] [/$] [path]");
puts(" ?,/?: help -- display this message");
puts(" /h: hidden -- include hidden directories/files in search");
puts(" /y system -- include system files in search (activates /h)");
puts(" /F: files -- display names of files found, not directories");
puts(" /s: summary -- follow directory/file list with directory/file counts");
puts(" /o: summary only -- display only a summary, no directory/file list");
puts(" /l: lower case -- display directory/file names in lower case");
puts(" /v: version -- display the current version of TRUNK");
puts(" /$: display information about TRUNK");
puts(" path: path -- the path of the directory in which to start TRUNK");
return;
}
} /* if (argc > 1) */
if (info) {
puts(version);
puts("\nThis version of TRUNK lies in the public domain and thus may be used by any");
puts("party for any purpose. Send comments, bug reports, and Ronettes albums to:\n");
puts("Mike O'Regan\n2739 Kingston Dr.\nNorthbrook, IL 60062\n");
return;
}
/**
*** If there are command line arguments, then the last one may be the
*** path to search on. If the last argument (argv[argc-1]) is not a flag,
*** then it is assumed to be the search path.
***
*** If there is a search path, but it is not a full path but merely a
*** drive specifier (such as from 'TRUNK D:') which is not the current
*** drive, then the operating system is called to change the current drive
*** to the search drive, the current working directory of that drive is
*** retrieved, and the current drive is reset to its original state.
*** NOTE: For now a reference to another drive w/o path ('TRUNK 'A:') will
*** start *at the root* of the specified drive.
***
*** If there is no search path in the command line, then the current
*** working directory is used as the search path.
**/
if ( (argc > 1) && (argv[argc-1][0] != '/') ) {
strcpy(search_ptr,argv[argc-1]);
strupr(search_ptr);
if ( (search_ptr[1] == ':') && (search_ptr[2] == '\0') ) {
if (search_ptr[0] == cwd_ptr[0]) {
search_ptr=cwd_ptr;
}
else {
strcat(search_ptr,"\\");
}
}
} /* if argc > 1 . . . */
else {
search_ptr=cwd_ptr;
}
/**
*** go for it
**/
if (force_lower)
strlwr(search_ptr);
delve(search_ptr);
if (summary) {
puti(dirs_found, " "," directories found");
puti(files_found, ", containing ", " files\n");
}
return;
}
/***************************************************************************/
/***************************************************************************/
/**
*** delve -- function that recursively steps down the directory structure
*** of a disk, either printing directories/files or just watching them
*** go by, according to the command line flags.
**/
/***************************************************************************/
/***************************************************************************/
int delve(unsigned char *parent_ptr)
{
struct find_t my_dta;
unsigned int find_result;
path current_path;
unsigned char *current_end;
/**
*** Copy the path passed from above, and stick "\*.*" at the end of it.
*** current_end ends up pointing to the spot at which to stick in file
*** when propigate(sp?) names down the line (i.e. the 3rd char from the
*** right in current_path).
**/
strcpy(current_path, parent_ptr);
current_end=strchr(current_path,'\0');
if (*(current_end-1) != '\\')
*(current_end++)='\\';
strcpy(current_end,"*.*");
/**
*** Find all the subdirectories in this directory. If there are no files
*** in this directory at all, then this must not be a valid directory, so
*** the parent pathname is not printed. The '.' and '..' directories
*** are duly ignored.
**/
find_result=_dos_findfirst(current_path, srch_attrib, &my_dta);
if (find_result == 0) {
if (print_dirs)
puts(parent_ptr);
++dirs_found;
}
while (find_result == 0) {
if ( my_dta.name[0] != '.' ) {
namecat(current_end, my_dta.name);
if (force_lower)
strlwr(current_end);
if ( my_dta.attrib & _A_SUBDIR ) {
delve(current_path);
}
else {
++files_found;
if (print_files)
puts(current_path);
}
} /* if my_dta.name[0] != '.' */
find_result=_dos_findnext(&my_dta);
}
return(0);
}
/***************************************************************************/
/***************************************************************************/
/**
*** puti -- written to avoid using printf, which would add 2K to the EXE
*** file size. The three arguments consist of the integer to print, a
*** pointer to a string to be printed before the integer, and a similar
*** pointer to be printed after the integer.
*** E.G.: puti(52,"There are "," cards in a deck.\n") yields
*** There are 52 cards in a deck.
**/
/***************************************************************************/
/***************************************************************************/
int puti(int the_int, char *pre_str, char *post_str)
{
char number[7];
int n=0;
itoa(the_int, number, 10);
while (*pre_str != '\0')
putchar(*(pre_str++));
while (number[n] != '\0')
putchar(number[n++]);
while (*post_str != '\0')
putchar(*(post_str++));
return(0);
}
/***************************************************************************/
/***************************************************************************/
/**
*** namecat -- function to take a filename from a dta--which is padded with
*** spaces--and turn it into a string, which is placed at *target_ptr.
**/
/***************************************************************************/
/***************************************************************************/
char *namecat(unsigned char *target_ptr, unsigned char *dta_name_ptr)
{
unsigned char *dest_ptr=target_ptr;
unsigned char ch;
if (*dta_name_ptr != '\0') /* properly handle *dta_name_ptr=='\0' */
while ( (ch=*(dta_name_ptr++)) != '\0') {
if (ch != ' ')
*(dest_ptr++)=ch;
}
*dest_ptr='\0';
return(target_ptr);
}